/**
 * @description 服务
 * @author Rid King
 * @since 2018-07-06
 */

import Model from '../../../model/2.0.0/js/model.js'
import objecter from '../../../objecter/2.0.0/js/objecter'
import parser from './parser'

/**
 * @class 服务类
*/
class Service extends Model{
  /**
   * @function 构造方法
  */
  constructor () {
    super()
    // 私有配置
    this._options = this.getDefaults() || {}
    // 成功与失败回调组
    this._resolves = []
    this._rejects = []
    // 事件绑定
    this.$on('onBeforeRequest', this.onBeforeRequest.bind(this))
    this.$on('onAfterRequest', this.onAfterRequest.bind(this))
  }

  /**
   * @function get请求
   * @return {Promise}
  */
  get () {
    let args = this.process.apply(this, arguments)
    args.method = METHOD.GET
	  return this.launch(args)
  }

  /**
   * @function post请求
   * @return {Promise}
  */
  post () {
    let args = this.process.apply(this, arguments)
    args.method = METHOD.POST
	  return this.launch(args)
  }

  /**
   * @function put请求
   * @return {Promise}
  */
  put () {
    let args = this.process.apply(this, arguments)
    args.method = METHOD.PUT
	  return this.launch(args)
  }

  /**
   * @function delete请求
   * @return {Promise}
  */
  delete () {
    let args = this.process.apply(this, arguments)
    args.method = METHOD.DELETE
    return this.launch(args)
  }

  /**
   * @function jsonp请求
   * @return {Promise}
  */
  jsonp () {
    let args = this.process.apply(this, arguments)
    args.method = METHOD.JSONP
    return this.launch(args)
  }

  /**
   * @function 请求数据
   * @param {Object} options // 配置对象
   * @return {Promise}
  */
  request (options) {
    let args = this.process.apply(this, arguments)
    args.method = args.method || METHOD.POST
	  return this.launch(args)
  }

  /**
   * @function 发起请求
   * @param {Object} options // 配置对象
   * @return {Promise}
  */
  launch (options) {
    // 前置处理
    let results = this.$emit('onBeforeRequest', options)
    // 允许发送请求
    let isAllow = true
    if (Array.isArray(results)) {
      results.forEach(item => {
        if (item === false) {
          isAllow = false
        }
      })
    }
    // 不允许发送
    if (!isAllow) {
      return Promise.reject({
        success: false,
        msg: 'Request cancled'
      })
    }

    // 请求数据
    let defer = this._send(options)
    // 返回异步处理对象
    defer = defer.then((result) => {
      let resultData = this.parse(
        result.response,
        result.options.dataType,
        result.options.isForceParse
      )
      // 后置处理
      this.$emit('onAfterRequest', result)
      return Promise.resolve(resultData)
    }, (result) => {
      let resultData = this.parse(
        result.response,
        result.options.dataType,
        result.options.isForceParse
      )
      // 后置处理
      this.$emit('onAfterRequest', result)
      return Promise.reject(resultData)
    })
    // 成功与失败回调
    this._resolves.forEach(item => {
      defer = defer.then(item)
    })
    this._rejects.forEach(item => {
      defer = defer.catch(item)
    })

    return defer
  }

  /**
   * @function 发送请求数据
   * @param {Object} options // 配置对象
   * @return {Promise}
  */
  _send (options) {
    return Promise.resolve({})
  }

  /**
   * @function 处理配置参数
   * @param {String/Object} url 访问地址
   * @param {String/Object} data 请求地址
   * @param {Object} options 配置
   * @param {Object} extra1 额外配置1
   * @param {Object} extra2 额外配置2
   * @return {Object}
   * */
  process (url, data, options, ...args) {
    // 处理配置对象
    if (objecter.isPlainObject(url)) {
      options = url
    }
    else if (objecter.isPlainObject(options)) {
      options.url = url || options.url
    }
    else {
      options = {
        url: url || ''
      }
    }

    // 处理数据、请求方式
    options.data = data || options.data || ''
    options.url = options.url || ''

    // 合并配置
    options = objecter.extend(
      {}, this._options,
      objecter.isPlainObject(options) ? options : {},
      ...args
    )
    // 请求头配置
    let headers = {}
    // 合并头
    objecter.forEach(this._options.headers, (item, key) => {
      headers[key] = item
    })
    headers = objecter.extend(
      headers,
      objecter.extend(
        {},
        options.headers
      )
    )
    // 生成头对象并设置属性
    options.headers = headers

    return options
  }

  /**
   * @function 请求管道操作
   * @param {Function} resolve // 成功回调
   * @param {Function} reject // 失败回调
   * @return {Promise}
  */
  pipe (resolve, reject) {
    // 成功回调组
    if (typeof resolve === 'function') {
      this._resolves.push(resolve)
    }
    // 失败回调组
    if (typeof reject === 'function') {
      this._rejects.push(reject)
    }

    return this
  }

  /**
   * @function 请求前处理
  */
  onBeforeRequest () {}

  /**
   * @function 请求后处理
  */
  onAfterRequest () {}

  /**
   * @function 模拟服务
   * @param {Object} options 配置对象
  */
  mock () {

  }

  /**
   * @function 数据对象转化为字符串
   * @param {Object} data // 数据对象
   * @return {String}
  */
  stringify (data) {
    return parser.stringify(data)
  }

  /**
   * @function 数据解析
   * @param {String} data // 数据字符串
   * @param {String} type // 数据类型,允许的值:object/array/
   * @param {Boolean} isForce // 是否强制转换
   * @return {String/Object}
  */
  parse (data, type, isForce) {
    return parser.parse(data, type, isForce)
  }

  /**
   * @function 设置配置
   * @param {Object} options // 配置对象
  */
  setOptions (options) {
    options = objecter.isPlainObject(options) ? options : {}
    this._options = objecter.extend(this._options, options)
  }

  /**
   * @function 默认配置
   * @return {Object}
  */
  getDefaults () {
    return {
      url: '',
      method: 'POST',
      data: '',
      // 请求头对象
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
      }
    }
  }
}

// 请求方式集合
const METHOD = {
  GET: 'get',
  POST: 'post',
  PUT: 'put',
  DELETE: 'delete',
  JSONP: 'jsonp'
}

export default Service